<template>

  <div class="flex-col">

    <!-- 头部样式 -->
    <div class="flex-row justify-center" style="margin-bottom: 5px;gap: 10px;">

      <!--   纸张尺寸   -->
      <a-button-group>
        <a-button v-for="(value,type) in paperTypes" :key="type" :type="curPaperType === type ? 'primary' : 'default'"
                  @click="setPaper(type,value)">
          {{ type }}
        </a-button>
        <a-popover v-model:value="paperPopVisible" title="设置纸张宽高(mm)" trigger="click">
          <template #content>
            <a-input-group compact style="margin: 10px 10px">
              <a-input type="number" v-model:value="paperWidth" style=" width: 100px; text-align: center"
                       placeholder="宽(mm)"/>
              <a-input style=" width: 30px; border-left: 0; pointer-events: none; backgroundColor: #fff"
                       placeholder="~" disabled
              />
              <a-input type="number" v-model:value="paperHeight"
                       style="width: 100px; text-align: center; border-left: 0"
                       placeholder="高(mm)"/>
            </a-input-group>
            <a-button type="primary" style="width: 100%" @click="otherPaper">确定</a-button>
          </template>
          <a-button :type="'other'==curPaperType?'primary':'default'">自定义纸张</a-button>
        </a-popover>
      </a-button-group>

      <!--   纸张自定义   -->
      <a-button @click="changeScale(false)" :icon="h(ZoomOutOutlined)"></a-button>
      <a-input-number
          :value="scaleValueRes"
          :min="scaleMin"
          :max="scaleMax"
          :step="0.1"
          disabled
          style="height: 32px;text-align: center;"
          :formatter="value => `${(value * 100).toFixed(0)}%`"
          :parser="value => value.replace('%', '')"
      />
      <a-button @click="changeScale(true)" :icon="h(ZoomInOutlined)"></a-button>

      <a-button type="primary" :icon="h(RedoOutlined)" @click="rotatePaper()">旋转</a-button>
    </div>

    <!--    -->
    <div class="flex-row justify-center" style="margin-bottom: 5px;gap: 10px;">
      <!--   格式   -->
      <a-radio-group>
        <a-radio-button @click="setElsAlign('left')" title="左对齐">
          <i class="iconfont sv-align-left"/>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('vertical')" title="居中">
          <span class="iconfont sv-align-center"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('right')" title="右对齐">
          <span class="iconfont sv-align-right"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('top')" title="顶部对齐">
          <span class="iconfont sv-align-top"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('horizontal')" title="垂直居中">
          <span class="iconfont sv-align-middle"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('bottom')" title="底部对齐">
          <span class="iconfont sv-align-bottom"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('distributeHor')" title="横向分散">
          <span class="iconfont sv-hline"></span>
        </a-radio-button>
        <a-radio-button @click="setElsAlign('distributeVer')" title="纵向分散">
          <span class="iconfont sv-distribute-vertical"></span>
        </a-radio-button>
      </a-radio-group>
    </div>

    <!--  头部按钮  -->
    <div class="flex-row justify-center" style="gap: 10px;">

      <!--   分页编辑   -->
      <div class="hiprint-printPagination"/>

      <a-button type="primary" :icon="h(EyeOutlined)" @click="preView()">
        预览
      </a-button>
      <a-button type="primary" @click="print()">
        浏览器打印
      </a-button>
      <a-button type="primary" @click="print2()">
        直接打印(需要连接客户端)
      </a-button>

      <a-button type="primary" @click="editTemplateData">
        编辑模板数据
      </a-button>

      <a-button type="primary" @click="editPrintData" >
        编辑打印数据
      </a-button>

      <!--   编辑模版和数据   -->
      <json-view ref="jsonViewTemplate" @updateFather="updateTemplate"/>

      <!--   保存   -->
      <a-button type="primary" @click="saveData()">
        保存
      </a-button>
    </div>

    <!--  编辑窗口  -->
    <div class="flex-row" style="height: 86vh;">

      <!--   左边   -->
      <div class="flex-2 left">
        <div class="flex-row justify-center flex-wrap">
          <div class="title">基础元素</div>
          <div class="ep-draggable-item item" tid="defaultModule.text">
            <i class="iconfont sv-text"/>
            <span>文本</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.image">
            <i class="iconfont sv-image"/>
            <span>图片</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.longText">
            <i class="iconfont sv-longText"/>
            <span>长文</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.table">
            <i class="iconfont sv-table"/>
            <span>表格</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.emptyTable">
            <i class="iconfont sv-table"/>
            <span>空表格</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.html">
            <i class="iconfont sv-html"/>
            <span>html</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.customText">
            <i class="iconfont sv-text"/>
            <span>自定义</span>
          </div>
          <div class="title">辅助元素</div>
          <div class="ep-draggable-item item" tid="defaultModule.hline">
            <i class="iconfont sv-hline"/>
            <span>横线</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.vline">
            <i class="iconfont sv-vline"/>
            <span>竖线</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.rect">
            <i class="iconfont sv-rect"/>
            <span>矩形</span>
          </div>
          <div class="ep-draggable-item item" tid="defaultModule.oval">
            <i class="iconfont sv-oval"/>
            <span>圆形</span>
          </div>

          <div class="ep-draggable-item item" tid="defaultModule.barcode">
            <i class="iconfont sv-barcode"/>
            <span>条形码</span>
          </div>

          <div class="ep-draggable-item item" tid="defaultModule.qrcode">
            <i class="iconfont sv-qrcode"/>
            <span>二维码</span>
          </div>

          <div class="title">
            自定义元素
          </div>
        </div>
      </div>

      <!--   中   -->
      <div class="flex-5 center">
        <!-- 设计器的 容器 -->
        <div id="hiprint-printTemplate"></div>
      </div>

      <!--   右   -->
      <div class="flex-2 right">
        <!-- 元素参数的 容器 -->
        <div id="PrintElementOptionSetting"></div>
      </div>

    </div>

  </div>

  <!-- 预览 -->
  <print-preview ref="preViewPrint"/>

</template>

<script setup>
import {computed, h, onMounted, reactive, ref} from "vue";
import {hiprint, defaultElementTypeProvider, disAutoConnect} from "vue-plugin-hiprint";
import {message} from "ant-design-vue";
import {
  EyeOutlined, RedoOutlined,
  ZoomInOutlined,
  ZoomOutOutlined
} from "@ant-design/icons-vue";
import printPreview from "@/components/preview.vue";
import jsonView from "@/components/jsonview.vue";
import {
  PageSize,
  defaultPaper,
  paperHeightSize,
  paperWidthSize,
  scaleValueResSize,
  scaleMaxSize, scaleMinSize
} from "@/utils/Constants.js"

// 初始化 provider
hiprint.init({
  providers: [defaultElementTypeProvider()],
});
disAutoConnect();


/**
 *通过这个引用对象来控制父组件向子组件传递数据，也可以调用子组件中的方法
 */
let jsonViewTemplate = ref()
const preViewPrint = ref()

//定义纸张大小
const paperTypes = reactive(PageSize);


let curPaper = ref(defaultPaper);
//用于判断是否展示修改后的新打印数据
let isPrintData = ref(true)
//初始化打印数据
let printData=ref({})
let isPrintOrTemplate = ref(true); // 是否编辑打印数据或模板



// 缩放
let scaleValueRes = ref(scaleValueResSize);
let scaleMax = ref(scaleMaxSize);
let scaleMin = ref(scaleMinSize);

// 自定义纸张
let paperPopVisible = ref(false);
const paperWidth = ref(paperWidthSize);
const paperHeight = ref(paperHeightSize);

const curPaperType = computed(() => {

  let type = 'other';
  let types = paperTypes;
  for (const key in types) {
    let item = types[key];
    let {width, height} = curPaper.value;
    if (item.width === width && item.height === height) {
      type = key;
    }
  }
  return type;
});

/**
 * 这里必须要在 onMounted 中去构建 左侧可拖拽元素 或者 设计器
 * 因为都是把元素挂载到对应容器中, 必须要先找到该容器
 */
onMounted(() => {
  buildLeftElement();
  window.buildDesigner(); // 调用全局方法
  init();
});

/**
 * 构建左侧可拖拽元素
 * 注意: 可拖拽元素必须在 hiprint.init() 之后调用
 * 而且 必须包含 class="ep-draggable-item" 否则无法拖拽进设计器
 */
const buildLeftElement = () => {
  // eslint-disable-next-line no-undef
  hiprint.PrintElementTypeManager.buildByHtml($(".ep-draggable-item"));
};

/**
 * 构建设计器
 * 注意: 必须要在 onMounted 中去构建
 * 因为都是把元素挂载到对应容器中, 必须要先找到该容器
 */
let hiprintTemplate;
window.buildDesigner = () => {
  //优先使用全局变量
  let temp = null;
  if(window.typrint && window.typrint.templateData){
      temp = window.typrint.templateData
  }

  if(window.typrint && window.typrint.printData){
    printData.value=window.typrint.printData
  }

  // eslint-disable-next-line no-undef
  $("#hiprint-printTemplate").empty(); // 先清空, 避免重复构建
  hiprintTemplate = new hiprint.PrintTemplate({
    template: temp,
    settingContainer: "#PrintElementOptionSetting", // 元素参数容器
    paginationContainer: '.hiprint-printPagination', // 多面板的容器， 实现多面板， 需要在添加一个 <div class="hiprint-printPagination"/>

    //添加字体样式选择
    fontList: [
      {title: '微软雅黑', value: 'Microsoft YaHei'},
      {title: '黑体', value: 'STHeitiSC-Light'},
      {title: '思源黑体', value: 'SourceHanSansCN-Normal'},
      {title: '王羲之书法体', value: '王羲之书法体'},
      {title: '宋体', value: 'SimSun'},
      {title: '华为楷体', value: 'STKaiti'},
      {title: 'cursive', value: 'cursive'},
    ],
  });

  // 构建 并填充到 容器中
  // 可以先 console.log($("#hiprint-printTemplate")) 看看是否有该 dom
  hiprintTemplate.design("#hiprint-printTemplate",{grid: true});
};

/**
 * 浏览器打印
 */
const print = () => {

      // 打印数据，key 对应 元素的 字段名
      // let printData = {name: "CcSimple"};
      // 参数: 打印时设置 左偏移量，上偏移量
      let options = {leftOffset: -1, topOffset: -1};
      // 扩展
      let ext = {
        callback: () => {
          console.log("浏览器打印窗口已打开");
        },
        //styleHandler: () => {
        // 重写 文本 打印样式
        //return "<style>.hiprint-printElement-text{color:red !important;}</style>";
        //},
      };

          hiprintTemplate.print(printData.value, options, ext);
      // 调用浏览器打印
    };
/**
 * 直接打印: 借助客户端,静默打印(无弹窗直接打印)
 * 注意: 需要先连接客户端
 */
const print2 = () => {
  if (hiprint.hiwebSocket.opened) {
    hiprintTemplate.print2({});
  } else {
    alert("请先连接客户端(刷新网页), 然后再点击「直接打印」");
  }
};

/**
 * 设置纸张大小
 * @param type [A3, A4, A5, B3, B4, B5, other]
 * @param value {width,height} mm
 */
const setPaper = (type, value) => {
  try {
    if (Object.keys(paperTypes).includes(type)) {
      curPaper.value = {type: type, width: value.width, height: value.height}
      hiprintTemplate.setPaper(value.width, value.height)
    } else {
      curPaper.value = {type: 'other', width: value.width, height: value.height}
      hiprintTemplate.setPaper(value.width, value.height)
    }
    paperWidth.value = value.width
    paperHeight.value = value.height
  } catch (error) {
    message.error(`操作失败: ${error}`)
  }
};

const otherPaper = () => {
  let value = {}
  value.width = paperWidth.value
  value.height = paperHeight.value
  paperPopVisible.value = false
  setPaper('other', value)
};


//缩放大小
function changeScale(big) {
  let scaleValue = scaleValueRes.value;
  if (big) {
    scaleValue += 0.1;
    if (scaleValue > scaleMax.value) scaleValue = 5;
  } else {
    scaleValue -= 0.1;
    if (scaleValue < scaleMin.value) scaleValue = 0.5;
  }
  if (hiprintTemplate) {
    // scaleValue: 放大缩小值, false: 不保存(不传也一样), 如果传 true, 打印时也会放大
    hiprintTemplate.zoom(scaleValue);
    scaleValueRes.value = scaleValue;
  }
};

function rotatePaper() {
  if (hiprintTemplate) {
    hiprintTemplate.rotatePaper()

  }
};

/**
 * 打印预览
 * @param value
 */
function preView(value) {
  //全局传的打印数据
  if (value) {
    preViewPrint.value.show(hiprintTemplate, value)
    return
  }
    preViewPrint.value.show(hiprintTemplate, printData.value)
}

function setElsAlign(e) {
  hiprintTemplate.setElsAlign(e)
};

function init() {
  jsonViewTemplate.value.template = hiprintTemplate
  // 获取当前放大比例, 当zoom时传true 才会有
  scaleValueRes.value = hiprintTemplate.editingPanel.scale || 1;
};

//进行修改打印数据以及模版数据
function updateTemplate(value) {

  const parsedValue = JSON.parse(value);

  if (!isPrintOrTemplate.value) {
    hiprintTemplate.update(parsedValue);
  } else {
    printData.value = parsedValue;
    preViewPrint.value.show(hiprintTemplate, parsedValue);
  }

  isPrintData.value = false;
}


//展示编辑模板数据弹窗
function editTemplateData(){
  jsonViewTemplate.value.showJsonData(hiprintTemplate.getJson())
  isPrintOrTemplate.value=false
}

//展示编辑打印数据弹窗
function editPrintData(){
  jsonViewTemplate.value.showJsonData(printData.value)
  isPrintOrTemplate.value=true
}

/**
 * 保存模板和打印数据
 */
function saveData(){
  if(window.typrint && window.typrint.saveData && typeof window.typrint.saveData === 'function'){
    let datas = {
      newTemplateData:hiprintTemplate.getJson(),
      newPrintData:printData.value
    }
    window.typrint.saveData(datas)
  }
}
window.preview = preView;
window.webPrint = print;
window.clientPrint= print2;
</script>

<style>
/* 重写全局 hiprint 样式 */
.hiprint-headerLine,
.hiprint-footerLine {
  border-color: #1677ff !important;
}

.hiprint-headerLine:hover,
.hiprint-footerLine:hover {
  border-top: 3px dashed #1677ff !important;
}

.hiprint-headerLine:hover:before {
  content: "页眉线";
  left: calc(50% - 18px);
  position: relative;
  background: #ffff;
  top: -14px;
  color: #1677ff;
  font-size: 12px;
}

.hiprint-footerLine:hover:before {
  content: "页脚线";
  left: calc(50% - 18px);
  position: relative;
  color: #1677ff;
  background: #ffff;
  top: -14px;
  font-size: 12px;
}

/* 区域 */
.left {
  background: white;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  padding: 10px 0;
  box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
  overflow: auto;
}

.center {
  margin: 0 10px;
  background: white;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  padding: 20px;
  box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
  overflow: auto;
}

.right {
  background: white;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  padding: 10px 0;
  box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
  overflow: auto;
}

/* 左侧拖拽元素样式 */
.title {
  font-size: 16px;
  font-weight: 500;
  width: 100%;
  margin: 10px 0 0 24px;
}

.item {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: white;
  padding: 4px 10px;
  margin: 10px 8px 4px 8px;
  width: 38%;
  min-height: 60px;
  border-radius: 4px;
  box-shadow: 2px 2px 2px 2px rgba(171, 171, 171, 0.2);
}

.item .iconfont {
  font-size: 1.5rem;
}

.item span {
  font-size: 14px;
}

</style>
